#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <iostream>

#include <QMainWindow>
#include <QtGui>
#include <math.h>

#include "simsock.h"
#include "chrum6lt.h"
#include "minimaestro.h"
#include "quaternionindicator.h"
#include "graphicalwindow.h"
#include "commandsindicator.h"
#include "recordwindow.h"
#include "newsettigswindow.h"
#include "simsrv.h"
#include "sensors.h"
#include "magnetometrwindow.h"


namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);

signals:
    void imu1Connected();
//    void getManualAngles();

private:
    void loadSettings();

    void setMainWindow();
    void createActions();
    void createSettingsWindow();
    void createTestWindow();

    void onGraphTimer(){graphicalWindow->setArmOrient(commVector);}
    void onHandTimer();
    void MRCSender(QVector<float>);

    QSettings *settings;
    QVector<float> commVector;

    bool isLeftArm;

    ChrUM6LT *imu1, *imu2;
    MiniMaestro *minimaestro;
    SimpleSocket *client;
    SimpleSocket *moveClient;
    SimpleServer *srv;
    QLabel *stsConnection;

    Ui::MainWindow *ui;
    GraphicalWindow *graphicalWindow;
    QWidget *settingsWindow, *testWindow, *boundariesWindow;
    RecordWindow *recordWindow;
    NewSettingsWindow *newSettingsWindow;
    MagnetometrWindow *magnetometrWindow;
    Sensors *sensorsWindow;


    QuaternionIndicator *qInd1, *qInd2;
    CommandsIndicator *commandsIndicator;

    QAction *exitAct;

    QPushButton *quitBtn;
    QPushButton *defCamBtn, *macroCamBtn, *backCamBtn, *profileCamBtn, *showSceneBtn, *testBtn;
    QPushButton *showRecordWindowBtn;
    QPushButton *connectAllBtn;
    QPushButton *zeroGyroBtn;
    QPushButton *reset_EKF_btn;
    QPushButton *settingsBtn;
    QPushButton *sensorsBtn;
    QCheckBox *checkBox;
    QCheckBox *tonusCheckBox;
    QCheckBox *standByCheckBox;
    QCheckBox *isLeftArmBox;
    QCheckBox *magnet_window_box;
    QCheckBox *soundFlag;
    QCheckBox *threeIMUFlag;
    QPushButton *armSendBtn, *handSendBtn, *sendBtn;
    bool autoConnectFlag;
    CalibrateButton *calibrateBtn;
    QCheckBox *autoPlayBox;

    QTimer *mainTimer;
    int timerCount;
    QTimer *sendTimer, *controlTimer, *dataTimer;
    QTimer *handReceiveTimer;


    QLineEdit *msgLe1, *msgLe2;

    bool sendFlag;
    bool armSendFlag;
    bool handSendFlag;
    bool tonusFlag;
    bool standByFlag;

    QQuaternion quater1, quater2, calQuat1, calQuat2, Q1, Q2;

    float k1, b1, k2, b2, k3, b3, k4, b4, k5, b5;
    QLineEdit *k1Edit, *k2Edit, *k3Edit, *k4Edit, *k5Edit;
    QLineEdit *b1Edit, *b2Edit, *b3Edit, *b4Edit, *b5Edit;
    QLineEdit *corAngLE;

    QLineEdit *forwardLE, *outLE, *rightLE, *upLE, *wristLE;
    QLineEdit *sho13LE, *sho24LE, *for13LE, *for24LE, *robowristLE;

    float forwardAng, outAng, rightAng, upAng, wristAng, rightAbsAng, upAbsAng;
    float sho13Comm, sho24Comm, for13Comm, for24Comm, wristComm;
    float corAng;

    unsigned char channelInd;
    QVector<int> gloveData;
    bool handReceiveFlag;
    bool recordFlag;


    QByteArray buffer;

    QVector<QString> portVector;

    bool magDataCollectionEnabled;
//    QVector<RawMagData> magDataVector;
//    QPushButton *collectMagDataBtn;
    bool manualControlFlag;

    QLineEdit *status_edit;

    QVector<int> angleBoundaries;
    QMap<short, QLineEdit*> angleBoundariesMap;
    bool useBoundariesFlag;
    int soundValue;

    bool recordStatus;

private slots:
    void showWindow();

    void showGraphicalWindow();
    void showRecordWindow();
    void showSettingsWindow(){settingsWindow->show();}
    void showAngleBoundariesWindow(){boundariesWindow->show();}
    void showNewSettingsWindow();
    void showSensorsWindow();

    void onClientConnect(QTcpSocket* socket);
    void onClientDisconnect(QTcpSocket* socket);
    void onRequest(QTcpSocket *socket, QString cmd, StringMap array);

    void getImuData();
    void armControl();

    void closeApp();
    void onCalibrateBtn();
    void editFactor();

    void onSendBtn(bool);
    void onTestBtn();
    void onConnectAllBtn();


    void clientSender(const QString &cmd);

    void ctrlWindowButton(int);

    void onByteRead(char ch);

    void onHandReceiveTimer(){handReceiveFlag = true;}
    void onSendTimer();
    void onMainTimer();

    void handSender(QVector<int>);

    void setCorAng(const QString &str){corAng = str.toInt();}


    void takeData();

    void aboutAHRS();

    void setPortVector(QString str);

    void zeroGyro();

    void replayMove(QVector<int>);

    void onNewSendBtn();
    void onArmSendBtn();
    void onHandSendBtn();

    void changeGloveSettings(int ind1, int ind2, int val);
    void changeArmSettings(int ind, float val);

    void onAutoPlayBox(){settings->setValue("AutoPlay", autoPlayBox->isChecked());}
    void saveAutoPlayXml(QString str){settings->setValue("AutoPlayXml", str);}

    void changeTypeOfArm(bool bl);
    void on_magnet_box(bool bl);
    void onSoundFlag(bool bl){settings->setValue("Sound", bl);}
    void onThreeIMUFlag(bool bl);

//    void onCollectMagDataBtn();


// About Magnetometr
    void onCollectingEnable(bool bl) {magDataCollectionEnabled = bl;}
//    void getCurrentMagCalibrationMatrix();


    void imuConnected(QString str);

    void onManualSignal(bool bl){manualControlFlag = bl;}

    void onWristSignal(int ind, int val);

    void createAngleBoundariesWindow();

    void onBoundariesChanged();
    void onUseBoundSignal(bool bl) {useBoundariesFlag = bl;}

    void onTakeDataIMU1(QQuaternion q);
    void onTakeDataIMU2(QQuaternion q){quater2 = q;}

    void onSendStringCommand(QString str, int com);
    void onSendRecordCommand(QString str, int com);
    void setDefaultPort(char ind, QString port)  {settings->setValue("port"+QString::number(ind), port);}

    void onRecordStatusChanged(bool isRecoding) {recordStatus = isRecoding;}
    void setOrientationOfArm(int ind,QQuaternion q) {graphicalWindow->setVirtualArm(ind, q);}

};

#endif // MAINWINDOW_H
